package com.tea.modules.java8.io.split;

import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * com.tea.modules.java8.io.split <br>
 * 使用NIO对文件进行切割
 *
 * @author jaymin
 * @since 2021/8/4
 */
@Slf4j
public class NioSpiltDemo {
    public static void main(String[] args) throws Exception {
        List<String> nioSplits = nioSpilt(new File("C:\\Users\\jaymin\\Desktop\\monitor\\[亲密关系（第5版）].(美).罗兰·米勒.(美)丹尼尔·珀尔曼.扫描版.pdf"), "C:\\Users\\jaymin\\Desktop\\monitor\\", 10 * 1024 * 1024);
        merge(nioSplits);
    }

    /**
     * 文件分片上传
     *
     * @param currentDir 分片后存放的位置
     * @param subSize    按多大分片
     * @throws Exception
     */
    public static List<String> nioSpilt(File file, String currentDir, double subSize) throws Exception {
        List<String> splitFileNames = new ArrayList<>();
        try (FileInputStream fis = new FileInputStream(file);
             FileChannel inputChannel = fis.getChannel();) {
            long splitSize = (long) subSize;
            long startPoint = 0;
            long endPoint = splitSize;
            for (int i = 1; i <= file.length(); i += subSize) {
                String name = currentDir + UUID.randomUUID() + ".tmp";
                splitFileNames.add(name);
                try (FileOutputStream fos = new FileOutputStream(name);
                     FileChannel outputChannel = fos.getChannel();) {
                    inputChannel.transferTo(startPoint, splitSize, outputChannel);
                    startPoint += splitSize;
                    endPoint += splitSize;
                }
            }
        }
        return splitFileNames;
    }

    /**
     * 合并切分的文件
     *
     * @param splitFiles
     * @throws Exception
     */
    public static void merge(List<String> splitFiles) throws Exception {
        File targetFile = new File("C:\\Users\\jaymin\\Desktop\\monitor\\合成.pdf");
        byte[] buffer = new byte[10 * 1024 * 1024];
        // 文件追加写入
        try (FileOutputStream fileOutputStream = new FileOutputStream(targetFile, true);) {
            splitFiles.forEach(splitFile -> {
                int len;
                try (FileInputStream fileInputStream = new FileInputStream(splitFile);) {
                    while ((len = fileInputStream.read(buffer)) != -1) {
                        fileOutputStream.write(buffer, 0, len);
                    }
                } catch (IOException e) {
                    log.error(e.getMessage());
                }
            });
        }
    }
}
